package cc.wfu.trigger.http;

import cc.wfu.type.annotation.PreAntAuthorize;
import cc.wfu.type.annotation.PreAntAuthorizeValue;
import cc.wfu.type.trigger.api.dto.JwtTokenRequest;
import cc.wfu.domain.auth.model.entity.AuthCodeEntity;
import cc.wfu.domain.user.model.entity.UserEntity;
import cc.wfu.trigger.api.IUserServiceApi;
import cc.wfu.trigger.api.dto.*;
import cc.wfu.types.exception.UserServiceException;
import cc.wfu.types.model.Response;
import com.alibaba.fastjson2.JSON;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * @Author: jia-qiang ljq1024.cc
 * @desc: 用户相关接口实现， 也是暴露给外部的controller
 * @Date: 2024-05-16-10:57
 */
@Slf4j
@AllArgsConstructor
@RequestMapping("/user/")
@RestController("user_controller")
//@CrossOrigin("${app.config.cross-origin}")
public class UserController extends UserControllerSupport implements IUserServiceApi {

    /**
     * 通过用户名【email】查询用户信息
     * @param email 用户邮箱
     * @return 用户信息json字符串
     */
    @Override
    @RequestMapping(value = "/query/user/info", method = RequestMethod.POST)
    public Response<String> queryUserEntity(@RequestParam("email") String email) {
        try {
            log.info("通过用户名【email】查询用户信息 - 开始，邮箱：{}", email);
            // 1. 参数校验
            if (!StringUtils.hasLength(email)) {
                log.warn("通过用户名【email】查询用户信息 - 参数错误【email is null】：{}",email);
                return Response.ILLEGAL_PARAMETER();
            }
            // 2. 查询
            UserEntity userEntity = userService.queryUser(email);
            return Response.SUCCESS(JSON.toJSONString(userEntity));
        } catch (UserServiceException e) {
            log.error("通过用户名【email】查询用户信息 - 失败 - error:{}", e.getMessage(), e);
            return Response.APP_ERROR(e.getMessage());
        } catch (Exception e) {
            log.error("通过用户名【email】查询用户信息 - 失败 - error: ", e);
            return Response.UN_ERROR();
        }
    }

    /**
     * 生成验证码
     * @param queryCodeRequest 邮箱参数
     */
    @Override
    @RequestMapping(value = "/code", method = RequestMethod.POST)
    public Response<String> queryCode(@RequestBody QueryCodeRequest queryCodeRequest) {
        try {
            String mail = queryCodeRequest.getEmail();
            log.info("生成验证码 - 开始，邮箱：{}", mail);
            String code = authService.generateCode(mail);
            log.info("生成验证码 - 结束，邮箱：{} - 验证码：{}", mail, code);
            return Response.SUCCESS();
        } catch (UserServiceException e) {
            log.error("生成验证码 - 失败 - error:{}", e.getMessage(), e);
            return Response.APP_ERROR(e.getMessage());
        } catch (Exception e) {
            log.error("生成验证码 - 失败 - error: ", e);
            return Response.UN_ERROR();
        }
    }

    /**
     * 用户注册接口
     * @param registerRequest email, code, password
     * @return 注册结果。
     */
    @Override
    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public Response<String> register(@Validated @RequestBody RegisterRequest registerRequest) {
        try {
            log.info("用户注册 - 开始，邮箱：{}", registerRequest.getEmail());
            // 1. 参数校验
            if (!StringUtils.hasLength(registerRequest.getCode()) || !StringUtils.hasLength(registerRequest.getPassword())) {
                log.warn("用户注册 - 参数错误：{}", registerRequest);
                return Response.ILLEGAL_PARAMETER();
            }
            // 2. 校验验证码是否正确
            authService.checkCode(AuthCodeEntity.builder().email(registerRequest.getEmail()).code(registerRequest.getCode()).build());
            log.info("验证码校验通过: {}", registerRequest.getCode());
            // 3. 注册，插入数据库
            userService.save(UserEntity.builder().username(registerRequest.getEmail()).password(registerRequest.getPassword()).build());
            log.info("用户注册 - 完成，邮箱：{}", registerRequest.getEmail());
            return Response.SUCCESS();
        } catch (UserServiceException e) {
            log.error("用户注册 - 失败 - error:{}", e.getMessage(), e);
            return Response.APP_ERROR(e.getMessage());
        } catch (Exception e) {
            log.error("用户注册 - 失败 - error: ", e);
            return Response.UN_ERROR();
        }
    }

    /**
     * 用户登录 - 接口
     * @param loginRequest email + password
     * @return 登录结果
     */
    @Override
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public Response<LoginResponse> login(@RequestBody LoginRequest loginRequest) {
        try {
            log.info("用户登录 - 开始，邮箱：{}", loginRequest.getEmail());
            // 1. 参数校验
            if (!StringUtils.hasLength(loginRequest.getPassword())) {
                log.warn("用户登录 - 参数错误【password is null】：{}", loginRequest);
                return Response.ILLEGAL_PARAMETER();
            }
            // 2.1 校验用户名【邮箱】是否正确
            UserEntity userEntity = userService.queryUser(loginRequest.getEmail());
            // 2.2 校验【密码】是否正确 - 未抛异常则成功
            authService.checkPassword(userEntity.getPassword(), loginRequest.getPassword());
            // 3. 生成jwtToken - 需要明文密码和用户名
            userEntity.setPassword(loginRequest.getPassword());
            String jwtToken = super.genJwtToken(JwtTokenRequest.builder().subject(JSON.toJSONString(userEntity)).build());
            // 4. 发送MQ消息，记录用户登录时间
            super.sendLoginMqMessage(loginRequest.getEmail());
            // 5. 返回结果
            return Response.SUCCESS(LoginResponse.builder()
                    .userId(userEntity.getUserId())
                    .token(jwtToken)
                    .email(userEntity.getUsername())
                    .build());
        } catch (UserServiceException e) {
            log.error("用户登录 - 失败 - error:{}", e.getMessage(), e);
            return Response.APP_ERROR(e.getMessage());
        } catch (Exception e) {
            log.error("用户登录 - 失败 - error: ", e);
            return Response.UN_ERROR();
        }
    }

    /**
     * 修改密码接口
     * @param updatePasswordRequest oldPassword + newPassword + verifyPassword
     * @param jwtToken token
     * @return 修改结果
     */
    @Override
    @RequestMapping(value = "/update/password", method = RequestMethod.POST)
    public Response<String> updatePassword(@RequestBody UpdatePasswordRequest updatePasswordRequest,
                                           @RequestHeader("Authorization") String jwtToken) {
        try {
            log.info("修改密码接口 - 开始");
            // 1. 参数校验
            String oldPassword = updatePasswordRequest.getOldPassword();
            String newPassword = updatePasswordRequest.getNewPassword();
            String verifyPassword = updatePasswordRequest.getVerifyPassword();
            if (!StringUtils.hasLength(oldPassword) || !StringUtils.hasLength(newPassword) || !StringUtils.hasLength(verifyPassword)) {
                log.warn("修改密码接口 - 参数错误【one of oldPassword,newPassword,verifyPassword is null】 - {}", updatePasswordRequest);
                return Response.ILLEGAL_PARAMETER();
            }
            // 2. 解析出邮箱【用户名】
            UserEntity verifyUserEntity = super.verifyEmailWithJwtToken(jwtToken);
            String email = verifyUserEntity.getUsername();
            // 3. 根据查询邮箱【用户名】用户信息
            UserEntity userEntity = userService.queryUser(email);
            // 4. 判断旧密码是否正确
            authService.checkPassword(userEntity.getPassword(), oldPassword);
            // 5. 判断两次密码是否相同
            if (!newPassword.equals(verifyPassword)) {
                log.warn("修改密码接口 - 参数错误【newPassword not equal verifyPassword】 - {}", updatePasswordRequest);
                return Response.ILLEGAL_PARAMETER();
            }
            // 6.更新密码
            userEntity.setPassword(authService.encode(updatePasswordRequest.getNewPassword()));
            userService.updatePassword(userEntity);
            return Response.SUCCESS();
        } catch (UserServiceException e) {
            log.error("修改密码接口 - 失败 - error:{}", e.getMessage(), e);
            return Response.APP_ERROR(e.getMessage());
        } catch (Exception e) {
            log.error("修改密码接口 - 失败 - error: ", e);
            return Response.UN_ERROR();
        }
    }

    // RILE_USER _ADMIN
//    @PreAuthorize("hasAnyRole('USER')")
//    @PreAntAuthorize(value = PreAntAuthorizeValue.hasAnyRole, antAuthorities = {"USER"})
    @RequestMapping(value = "/test", method = RequestMethod.GET)
    public String test() {
        return "test";
    }

}
